<?php

namespace Core\annotationhandlers;

use Core\annotations\Redis;
use Core\BeanFactory;
use Core\init\DecorateCollector;
use Core\lib\RedisHelper;


function getKey(string $key, array $params)
{
    //#对应的是请求参数的第几个 需要跟  public function redisTest(int $uid, string $name)
    $patten = "/^#(\d+)/i";
    if (preg_match($patten, $key, $matches)) {
        //匹配成功 且 对应参数是字符串或 数字时返回对应的
        if (isset($params[$matches[1]]) && (is_string($params[$matches[1]]) || is_numeric($params[$matches[1]]))) {
            return $params[$matches[1]];
        }
    }
    return $key;
}

function getKeyForData(string $key, array $array)
{
    $patten = "/^#(\w+)/i";
    if (preg_match($patten, $key, $matches)) {
        if (isset($array[$matches[1]]) && (is_string($array[$matches[1]]) || is_numeric($array[$matches[1]]))) {
            return $array[$matches[1]];
        }
    }
    return $key;
}

function RedisStringHandle(Redis $redis, array $params, $func)
{
    $key = $redis->prefix . "_" . getKey($redis->key, $params);
    $redisData = RedisHelper::get($key);
    if ($redisData) {
        return json_decode($redisData, true);
    }
    $redisData = call_user_func($func, ...$params);
    if ($redis->expire > 0) {
        RedisHelper::setex($key, $redis->expire, json_encode($redisData));
    } else {
        RedisHelper::set($key, json_encode($redisData));
    }
    return $redisData;
}

function RedisHashHandle(Redis $redis, array $params, $func)
{
    $key = $redis->prefix . "_" . getKey($redis->key, $params);
    $redisData = RedisHelper::hGetAll($key);
    if ($redisData) {
        if ($redis->incr) {
            RedisHelper::hIncrBy($key, $redis->incr, 1);
        }
        return $redisData;
    }
    $redisData = call_user_func($func, ...$params);
    //哈希设置过期时间需要通过其他方式
    if (is_object($redisData)) {
        $redisData = json_decode(json_encode($redisData), true);
    }
    $dataKeys = array_keys($redisData);
    $dataKeys = implode('', $dataKeys);
    if (preg_match("/^\d+$/", $dataKeys)) {
        foreach ($redisData as $value) {
            RedisHelper::hMSet($redis->prefix . "_" . getKeyForData($redis->key, $value), $value);
        }
    } else {
        RedisHelper::hMSet($key, $redisData);
    }
    return $redisData;
}

function RedisSortedSetHandle(Redis $redis, array $params, $func)
{
    $redisData = call_user_func($func, ...$params);
    if ($redis->coroutine) {
        echo "111" . PHP_EOL;
        $redisData = $redisData->pop();
    }
    if (is_object($redisData)) {
        $redisData = json_decode(json_encode($redisData), true);
    }
    foreach ($redisData as $val) {
        RedisHelper::zAdd($redis->prefix, $val[$redis->score], $redis->member . $val[$redis->key]);
    }
    return $redisData;
}

return [
    Redis::class => function (\ReflectionMethod $method, $instance, Redis $redis) {
        $collector = BeanFactory::getBean(DecorateCollector::class);
        /**@var $collector  DecorateCollector* */
        $key = get_class($instance) . "::" . $method->getName();
        if (isset($collector->dSet[$key])) {
            return $instance;
        }
        //装饰器 收集
        $collector->dSet[$key] = function ($func) use ($redis) {
            return function ($params) use ($func, $redis) {
                if ($redis->key) {
                    switch ($redis->type) {
                        case "string":
                            return RedisStringHandle($redis, $params, $func);
                        case "hash":
                            return RedisHashHandle($redis, $params, $func);
                        case "sortedset":
                            return RedisSortedSetHandle($redis, $params, $func);
                        default:
                            return call_user_func($func, ...$params);
                    }
                }
                return call_user_func($func, ...$params);
            };
        };
    },
];
